/*
Web: http://www.jsForms.com
Copyright (C) 2008  Igor Demyanov (mailto:Igor.Demyanov@gmail.com)
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
jsForms.Components.CssSelectorProperty={
	SetName:function(value)
	{
		this.C.pName.val(value);
		return this;
	},
	SetValue:function(value)
	{
		this.C.pValue.val(value);
		return this;
	},
	GetValue:function()
	{
		return this.C.pValue.val();
	},
	GetName:function()
	{
		return this.C.pName.val();
	}
};
jsForms.Components.CssConfig = {
	Init:function()
	{
		this.C.propList.bind('dblclick',this,this.dblclick_AddProperty);
		this.C.cssSelectorName.bind('change',this,this.change_CssSelector);
		return jsForms.Components.Component.Init.call(this);
	},
	change_CssSelector:function(e)
	{
		if (!e.data) {
			return;
		}
		e.data.ChangeCssSelector();
	},
	dblclick_AddProperty:function(e)
	{
		if (!e.data) {
			return;
		}
		var newW = cssController.AddProperty('','');
		e.data.C.propList.append(newW);
	},
	ChangeCssSelector:function()
	{
		var newSelectorName = this.C.cssSelectorName.val();
		this.SetSelector(newSelectorName);
	},
	InsertCssSelector:function(className)
	{
		var item='.'+className;
		$('<option/>').attr('value',item).text(item).appendTo(	this.C.cssSelectorName);
		this.C.cssSelectorName.val(item);
		this.ChangeCssSelector();
	},
	Insert_onClick:function()
	{
		if (this.P.Node != undefined) {
			this._ExecEvent('onInsert');
		}
	},
	DeleteCssSelector:function()
	{
		if (confirm('Delete?')!=true)
		{
			return;
		}
		if (this.P.cssClassName != undefined) {
			var classes = this.P.cssClassName.split('.');
			for (var i in classes) {
				jsForms.DesignMode.RemoveCSSClass(this.P.Node,classes[i]);
			}
		}
		cssController.DeleteCSSSelector(this.P.cssClassName);
		this._ExecEvent('onChange');
	},
	ApplySetting:function()
	{
		if (this.P.cssClassName == '')
		{
			return;
		}
		if (this.P.isRawCss != true) {
			cssController.Apply();
		}
		else
		{
			cssController.UpdateCssSelector(this.P.cssClassName,this.C.sourceCSS.GetSource());
			this.UpdateProperties();
		}
		if (this.P.cssClassName != undefined) {
			var classes = this.P.cssClassName.split('.');
			for (var i in classes) {
					jsForms.DesignMode.AddCSSClass(this.P.Node,classes[i]);
			}
		}
		this._ExecEvent('onChange');
		return this;
	},
	Clear:function()
	{
		this.C.propList[0].innerHTML ='';
		this.C.cssSelectorName.empty();
		//$('<option/>').attr('value','').text('NONE').appendTo(	this.C.cssSelectorName);
		this.C.cssSelectorName.val('');
		this.P.Node = undefined;
		this.P.cssClassName = undefined;
		this.P.generateCss = false;
		if (this.P.isRawCss==true)
		{
			this.C.sourceCSS.SetSource(' ');
		}
		return this;
	},
	SetObject:function(node)
	{
		this.Clear();
		if(!node || node.isText == true)	
		{
			return this;
		}
		this.P.Node = node;

		var list = [];
		var tmpA = node.Attributes['CLASS'];
		if (tmpA && tmpA.value)
		{
		  var designClass = tmpA.value.replace(/ +/g,' ').split(' ');
		  if (!list.indexOf)
		  {
		  	list.indexOf = jsForms.indexOf;
		  }
		  for (var i = 0; i<designClass.length ; i++)
		  {
		  	var item = designClass[i];
		  	if (list.indexOf(item)==-1)
			{
				list.push(item);
			}
		  }
		}
		/*if (node.isText != true && node.Real)
		{
		  list = node.Real.className.replace(/ +/g,' ').split(' ');
		}*/
		
		var first;
		for(var i = 0; i<list.length ; i++)
		{
			var item = $.trim(list[i]);
			if (!first)
			{
				first = item;
			}
			if (item!='')
			{
				item='.'+item;
				$('<option/>').attr('value',item).text(item).appendTo(	this.C.cssSelectorName);
			}
		}
		if (first != undefined) {
			this.C.cssSelectorName.val(first);
			this.ChangeCssSelector();
		}
		return this;
	},
	SetSelector :function(newClass)
	{
		this.P.cssClassName = newClass; 
		cssController.SetCssSelector(newClass);
		this.UpdateProperties();
		this.UpdateRAW();
		return this;
	},
	UpdateRAW:function()
	{
		if (this.P.isRawCss!=true)
		{
			return;
		}
		this.C.sourceCSS.SetSource(cssController.GetCssSelectorBody());
	},
	UpdateProperties:function()
	{
		var propList = this.C.propList;
		propList[0].innerHTML ='';
		cssController.Update();
		var list = cssController.SelectorProperties;
		for (var i in list)
		{
			var value = list[i];
			propList.append(value);
		}
		return this;
	},
	SelectRawTab:function()
	{
		this.P.isRawCss=true;
		this.C.sourceCSS.Show();
		this.UpdateRAW();
	},
	DeselectRawTab:function()
	{
		this.P.isRawCss=false;
		//this.C.sourceCSS.Hide();
	}
	
};

jsForms.CreateCompileInfoByObject(
{
	Name: 'CssConfig',
	Properties: {
	},
	Events: {
		onChange: {},
		onInsert: {}
	}
});

var cssController = {
	Init: function()
	{
		this.head = $('head');
	},
	GetCssSelector:function(selectorName)
	{
		var cssClass = $('style[@cssClass="'+selectorName+'"]',this.head);
		if (cssClass.length == 0)
		{
			return;
		}else{
			return cssClass;
		}
	},
	GetSpecialClass:function(componentType,classes)
	{
		var list = classes.split(' ');
		for(var i in list)
		{
			if (list[i].indexOf(componentType)!= -1)
			{
				return list[i];
			}
		}
		return;
	},
	GenerateSpecialClass:function(componentType)
	{
		var index = 0;
		while(true)
		{
			var genName = componentType+index.toString();
			if (this.GetCssSelector('.'+genName)== undefined)
			{
				return genName;
			}else
			{
				index ++;
			}
		}
	},
	GetCssSelectorBody:function()
	{
		if (!this.selCSS)
		{
			return '';
		}else
		{
			var cssText = this.selCSS.text();
			var v = this.ParseSelector(cssText);
			if (v)
			{
			return v.body.replace(/[\n\t]*/g,'')
				.replace(/;/g,';\n');
			}
			else
			{
			return '';
			}
		}
	},
	/*GetCssSelector:function()
	{
		return this.selCSS;
	},*/
	SetCssSelector:function(selectorName)
	{
		 //'<STYLE type="text/css" cssClass="">'
		var cssClass = this.GetCssSelector(selectorName);
		this.generateCSS=false;
		if (!cssClass)
		{
			this.generateCSS=true;
			//cssClass = this.AddCssSelector(selectorName,'');
		}
		this.selCSSSelectorName = selectorName;
		this.selCSS = cssClass;
		this.Update();
	},
	Update: function()
	{
		if (this.SelectorProperties != undefined)
		{
			delete(this.SelectorProperties);
		}
		this.SelectorProperties = [];
		if (this.selCSS==undefined)
		{
			return;
		}
		var cssText = this.selCSS.text();
		var v = this.ParseSelector(cssText);
		if (v)
		{
			this.ParseSelectorBody(v.body);
		}
	},
	Apply:function()
	{
		if (this.generateCSS==true)
		{
			this.generateCSS=false;
			this.selCSS = this.AddCssSelector(this.selCSSSelectorName,'');
		}
		var tmp = [];
		var list = this.SelectorProperties;
		tmp.push(this.selCSSSelectorName);
		tmp.push('{');
		for (var i in list)
		{
			var value = list[i];
			tmp.push(value.GetName()+':'+value.GetValue()+';');
		}
		tmp.push('}');
		this.selCSS.text(tmp.join(''));
	},
	ParseCSSText: function(sText)
	{
		var sText = sText.replace(/[\t\r\n]+/g, '').replace(/:[ ]+/g,':');
			//#region Remove comments
		
			while (sText.search(this.startComent)!= -1)//Remove comments
			{
				var startComment  = sText.search(this.startComent);
				var endComment = sText.search(this.endComent);
				if (endComment == -1) {
					sText = sText.substr(0,startComment);//sText.remove(startComment);
				}
				else {
					sText = sText.substr(0,startComment)+sText.substr(endComment+2);
				}
			}
			//#endregion
			
			var classM = sText.match(this.selectorSplit);
				for (var Sclass in classM)
				{
					var classStr = classM[Sclass];
					var select = this.ParseSelector(classStr);
					if (select) {
						this.UpdateCssSelector(select.name, select.body);
					}
				}
	},
	ParseSelectorBody:function(selectorBody)
	{
		if (this.SelectorProperties == undefined) {
		
			this.SelectorProperties = [];
		}
		
		var properties = selectorBody.split(';');
		for (var p in properties)
		{
			var value = properties[p];
			if (!value || $.trim(value) == '') continue;
			
			var values = value.split(':',2);
			var pName;
			if (values[0])
			{
				pName = $.trim(values[0]);
			}else{pName = '';}
			var pValue;
			if (values[1])
			{
				pValue = values[1];
			}else{pValue = '';}
			this.AddProperty(pName,pValue);
		}
	},
	AddProperty:function(pName,pValue)
	{
		var obj = jsForms.CreateComponent('CssSelectorProperty');
		if (!this.SelectorProperties)
		{
			this.SelectorProperties = [];
		}
		this.SelectorProperties.push(obj);
		obj.SetName(pName);	
		obj.SetValue(pValue);
		return obj;
	},
	ParseSelector:function(classStr)
	{
		var classNames = $.trim(classStr.match(this.classNameDetect).toString());
		var classDef = classStr.match(this.classDefine).toString();

		if (classDef.length ==0)
		{
			return;
		}

		return {
			name: classNames,
			body: classDef.substr(1, classDef.length - 2)
		};
	},
	UpdateCssSelector:function(selectorName,selectorBody)
	{
		var selector = this.GetCssSelector(selectorName);
		if (selector) {
			//selector.remove();
			this.UpdateCssSelectorBody(selector,selectorName,selectorBody);
			//selector.appendTo(this.head);
		}
		else {
			this.AddCssSelector(selectorName, selectorBody);
		}
	},
	UpdateCssSelectorBody:function(selectorObj,selectorName,body)
	{
		selectorObj.text(this.FormatingCSSSelector(selectorName+'{'+body+'}'));
	},
	DeleteCSSSelector:function(selectorName)
	{
		var selector = this.GetCssSelector(selectorName);
		if (selector) {
			selector.remove();
		}
	},
	AddCssSelector:function(selectorName,selectorBody)
	{
			var cssClass = $('<STYLE type="text/css" cssClass="'+selectorName+'"/>').appendTo(this.head);		
			this.UpdateCssSelectorBody(cssClass,selectorName,selectorBody);
			return cssClass;
	},
	FormatingCSSSelector:function(text)
	{
		return text.replace(/[\n\t]*;[\n\t]*/g,';')
				.replace(/;/g,';\n\t')
				.replace(/[\n\t]*\}/g,'\n}')
				.replace(/[\n\t]*\{[\n\t]*/g,'\n{\n\t');
	},
	GenerateCSSFile:function()
	{
		var items = $('style',this.head);
		var fileText = [];
		for (var i=0 ; i<items.length;i++)
		{
			var item = items[i];
			var cssClass = item.getAttribute('cssClass');
			if (cssClass == undefined || cssClass==null)
			{
				continue;
			}
			fileText.push(this.FormatingCSSSelector(item.innerHTML));
		}
		return fileText.join('\n');
	},
	startComent:/\/\*/,
	endComent : /\*\//,
	classDetect : /[^*/{]*\s*{\s*[^}]*}/,
	classNameDetect : /[^{]*/,
	selectorSplit : /[^}]*}/g,
	classDefine :/{[^}]*}/
};
